package yx.action;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.springframework.beans.factory.annotation.Autowired;

import yx.model.BsAttendance;
import yx.service.AttendanceServiceInt;
import yx.service.CourseServiceInt;
import yx.service.StudentServiceInt;
import yx.utils.DateUtils;
import yx.utils.ExcelUtils;
import yx.vo.AttendanceVO;
import yx.vo.CourseVO;
import yx.vo.DatagridVO;
import yx.vo.GradeVO;
import yx.vo.JsonVO;
import yx.vo.StudentVO;

import com.opensymphony.xwork2.ModelDriven;

@ParentPackage("basePackage")
@Namespace("/")
@Action(value = "attendanceAction")
public class AttendanceAction extends BaseAction implements ModelDriven<AttendanceVO> {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(AttendanceAction.class);

	private AttendanceVO attendance = new AttendanceVO();

	@Override
	public AttendanceVO getModel() {
		return attendance;
	}

	private AttendanceServiceInt attendanceService;
	private StudentServiceInt studentService;
	private CourseServiceInt courseService;

	public AttendanceServiceInt getAttendanceService() {
		return attendanceService;
	}

	@Autowired
	public void setAttendanceService(AttendanceServiceInt attendanceService) {
		this.attendanceService = attendanceService;
	}

	public StudentServiceInt getStudentService() {
		return studentService;
	}

	@Autowired
	public void setStudentService(StudentServiceInt studentService) {
		this.studentService = studentService;
	}

	public CourseServiceInt getCourseService() {
		return courseService;
	}

	@Autowired
	public void setCourseService(CourseServiceInt courseService) {
		this.courseService = courseService;
	}

	public void queryAttendance() {
		super.writeJson(attendanceService.datagrid(attendance));
	}

	public void addAttendance() {
		JsonVO j = new JsonVO();
		try {
			AttendanceVO u = attendanceService.save(attendance);
			j.setSuccess(true);
			j.setMsg("增加成功！");
			j.setObj(u);
		} catch (Exception e) {
			j.setMsg(e.getMessage());
		}
		super.writeJson(j);
	}

	public void removeAttendance() {
		attendanceService.remove(attendance.getIds());
		JsonVO j = new JsonVO();
		j.setSuccess(true);
		j.setMsg("删除成功！");
		super.writeJson(j);
	}

	public void editAttendance() {
		AttendanceVO u = attendanceService.edit(attendance);
		JsonVO j = new JsonVO();
		j.setSuccess(true);
		j.setMsg("编辑成功！");
		j.setObj(u);
		super.writeJson(j);
	}

	public void importAttendance() {
		// 请假标识对应Map
		Map<String, String> leaveFlagMap = new HashMap<String, String>();
		leaveFlagMap.put("01", "请假");
		leaveFlagMap.put("02", "未请假");
		// 出勤标识对应Map		
		Map<String, String> attendanceFlagMap = new HashMap<String, String>();
		attendanceFlagMap.put("01", "出勤");
		attendanceFlagMap.put("02", "缺勤");
		// 上班时段对应Map		
		Map<String, String> classTypeMap = new HashMap<String, String>();
		classTypeMap.put("01", "上午班");
		classTypeMap.put("02", "下午班");
		classTypeMap.put("03", "晚上班");
		
		JsonVO j = new JsonVO();
		try {
			// 第一步：读取预置的模板
			String templatePath = ServletActionContext.getServletContext().getRealPath("/") + "template\\AttendanceImport.xlsx";
			Map<Integer, Boolean> mapCell = ExcelUtils.resolveExcelTemplate(templatePath);
			InputStream inp = new FileInputStream(attendance.getImportAttendance());
			XSSFWorkbook wb = new XSSFWorkbook(inp);
			int countCell = mapCell.size(); // 模板 列数
			List<BsAttendance> importAttendanceList = new ArrayList<BsAttendance>();
			// 导入列里 已经存在的 用户编码 集合 K用户编码 V所在Excel中第几行
			Map<String, Integer> importAttendanceMap = new HashMap<String, Integer>();
			XSSFSheet sheet = wb.getSheetAt(0); // 只 读取 第一个 sheet
			if (sheet.getLastRowNum() == 0) {
				throw new Exception("导入文件中数据不存在！");
			}
			int rownum = sheet.getLastRowNum() + 1;
			XSSFRow row = sheet.getRow(0);
			int cellnum = row.getLastCellNum();
			if (cellnum != countCell) {
				throw new Exception("数据格式和模板不一致！");
			}
			// Key：行号 Value：行的错误ArrayList
			Map<String, List<String>> errorMap = new HashMap<String, List<String>>();

			int startDate = 0; // 授课日期

			// 遍历数据行 从 索引为1开始 因为第一行是标题
			for (int index = 1; index < rownum; index++) {
				row = sheet.getRow(index);
				if (row == null || row.getLastCellNum() == 0)
					continue;
				List<String> dataList = new ArrayList<String>();
				List<String> errorList = new ArrayList<String>();
				String r1c1Cell = null;
				for (int cellindex = 0; cellindex < cellnum; cellindex++) {
					XSSFCell cell = row.getCell(cellindex);
					String cellStr = ExcelUtils.getExcelCellValue(cell);
					if (cellindex == 0) {
						r1c1Cell = cellStr;
					}
					if (mapCell.get(cellindex) && cell == null) {
						errorList.add("第" + (cellindex + 1) + "列不能为空！");
					} else {
						if (cellindex == 1 && cell != null) { // 第二列为学号且姓名+学号不能重复
							if (!importAttendanceMap.containsKey(cellStr)) {
								StudentVO stuVO = new StudentVO();
								stuVO.setStudentName(r1c1Cell);
								stuVO.setStudentNo(cellStr);
								StudentVO stu = hasStudent(stuVO.getStudentName(), stuVO.getStudentNo());
								if (stu == null) {
									errorList.add("第" + (cellindex + 1) + "列[姓名+学号]不存在！");
									cellStr = null;
								} else {
									cellStr = stu.getId().toString();
									importAttendanceMap.put(cellStr, cellindex + 1);
								}
							} else {
								errorList.add("第" + (cellindex + 1) + "列[学号]与Excel第" + importAttendanceMap.get(cellStr) + "行学号相同！");
								cellStr = null;
							}
						}
						if (cellindex == 2 && cell != null) { // 第三列为课程名称
							CourseVO courseVO = new CourseVO();
							courseVO.setCourseName(cellStr);
							CourseVO c = hasCourse(courseVO);
							if (c == null) {
								errorList.add("第" + (cellindex + 1) + "列[课程名称]不存在！");
								cellStr = null;
							} else {
								cellStr = c.getId().toString();
							}
						}
						if (cellindex == 3 && cell != null) { // 第四列为授课日期
							if ((cellStr.indexOf("/") == -1) && (cellStr.indexOf("-") == -1)) {
								errorList.add("第" + (cellindex + 1) + "列[授课日期]格式不正确！");
							} else {
								if (cellStr.length() != 10) {
									errorList.add("第" + (cellindex + 1) + "列[授课日期]格式不正确！");
								} else {
									String startDateStr = "";
									if (cellStr.indexOf("/") != -1) {
										startDateStr = cellStr.replace("/", "-");
										cellStr = startDateStr;
									}
								}
							}
						}
						if (cellindex == 4 && cell != null) { // 第三列为授课时段
							if (classTypeMap.values().contains(cellStr)) {
								for(String key : classTypeMap.keySet()){
									String val = classTypeMap.get(key);
									if(val.equals(cellStr)){
										cellStr = key;
										break;
									}
								}
							} else {
								errorList.add("第" + (cellindex + 1) + "列[授课时段]输入不正确！");
								cellStr = null;
							}
						}
						if (cellindex == 5 && cell != null) { // 第三列为是否出勤
							if (attendanceFlagMap.values().contains(cellStr)) {
								for(String key : attendanceFlagMap.keySet()){
									String val = attendanceFlagMap.get(key);
									if(val.equals(cellStr)){
										cellStr = key;
										break;
									}
								}
							} else {
								errorList.add("第" + (cellindex + 1) + "列[是否出勤]输入不正确！");
								cellStr = null;								
							}
						}
						if (cellindex == 6 && cell != null) { // 第三列为是否请假
							if (leaveFlagMap.values().contains(cellStr)) {
								for(String key : leaveFlagMap.keySet()){
									String val = leaveFlagMap.get(key);
									if(val.equals(cellStr)){
										cellStr = key;
										break;
									}
								}
							} else {
								errorList.add("第" + (cellindex + 1) + "列[是否请假]输入不正确！");
								cellStr = null;								
							}
						}
					}
					dataList.add(cellStr);
					errorMap.put((index + 1) + "", errorList);
				}
//				Integer studentId = Integer.valueOf(dataList.get(1));
//				Integer courseId = Integer.valueOf(dataList.get(2));
//				boolean ret = hasAttendance(studentId, courseId);
//				if (ret) {
//					errorList.add("导入数据已经存在！");
//				}
				StringBuffer rowErrMsgSb = new StringBuffer("");
				List<String> tempList = errorMap.get((index + 1) + "");
				if (tempList != null) {
					for (int n = 0; n < tempList.size(); n++) {
						String str = (String) tempList.get(n);
						rowErrMsgSb.append(str);
					}
				}

				// 判断当前行是否有错
				if ("".equals(rowErrMsgSb.toString())) {
					BsAttendance importAttendance = new BsAttendance();
					importAttendance.setStudentId(Integer.valueOf(dataList.get(1)));
					importAttendance.setCourseId(Integer.valueOf(dataList.get(2)));
					Date teachingDate = DateUtils.stringToDate(dataList.get(3), null);
					importAttendance.setTeachingDate(teachingDate);
					importAttendance.setClassType(dataList.get(4));
					importAttendance.setAttendanceFlag(dataList.get(5));
					importAttendance.setLeaveFlag(dataList.get(6));
					importAttendance.setMemo(dataList.get(7));
					importAttendanceList.add(importAttendance);
				}
			}

			// 判断是否有错
			StringBuffer tempErrMsg = new StringBuffer("");
			for (int ind = 1; ind <= rownum; ind++) {
				List<String> tempList = errorMap.get(ind + "");
				if (tempList != null) {
					for (int t = 0; t < tempList.size(); t++) {
						String str = (String) tempList.get(t);
						tempErrMsg.append(str);
					}
				}
			}

			// 出错处理
			StringBuffer allErrMsg = new StringBuffer("");
			if (!"".equals(tempErrMsg.toString())) {
				for (int ind = 1; ind <= rownum; ind++) {
					List<String> errList = errorMap.get(ind + "");
					String tempErr = "";
					if (errList == null || errList.size() == 0) {
						// 无错
						continue;
					} else {
						StringBuffer sb = new StringBuffer();
						sb.append("第" + ind + "行：");
						java.util.Iterator it = (java.util.Iterator) errList.iterator();
						while (it.hasNext()) {
							String item = (String) it.next();
							sb.append(item + ",");
						}
						tempErr = sb.toString().substring(0, sb.toString().length() - 1) + "\\n";
					}
					allErrMsg.append(tempErr);
				}
				throw new Exception(allErrMsg.toString());
			} else {
				attendanceService.saveAll(importAttendanceList);
				j.setSuccess(true);
				j.setMsg("导入成功！");
				super.writeJson(j);
			}
		} catch (Exception e) {
			j.setMsg(e.getMessage());
			super.writeJson(j);
		}
	}
	
	public void downloadTemplate() {
		OutputStream os = null;
		byte[] bytes = null;
		try {
			String downloadPath = ServletActionContext.getServletContext().getRealPath("/") + "template\\AttendanceImport.xlsx";
			bytes = attendanceService.getFileBytes(downloadPath);
			ServletActionContext.getResponse().reset();
			ServletActionContext.getResponse().setCharacterEncoding("utf-8");
			ServletActionContext.getResponse().setHeader("Content-Type", "application/octet-stream");
			ServletActionContext.getResponse().setHeader("Content-Disposition", "attachment; filename=AttendanceImport.xlsx");
			os = ServletActionContext.getResponse().getOutputStream();
			if (bytes != null) {
				os.write(bytes);
				os.flush();
				os.close();
			}
			logger.info("文档下载成功！");
		} catch (Exception e) {
			logger.error("文档下载失败！");
		} finally {
			try {
				if (bytes != null) {
					os.write(bytes);
					os.flush();
				}
				os.close();
			} catch (IOException e) {
				logger.error("流文件关闭异常！");
			}
		}
	}

	private StudentVO hasStudent(String studentName, String studentNo) {
		StudentVO vo = null;
		List<StudentVO> list = studentService.queryStudentByNameAndNo(studentName, studentNo);
		if (list.size() > 0) {
			vo = list.get(0);
			return vo;
		}
		return vo;
	}

	private CourseVO hasCourse(CourseVO course) {
		DatagridVO vo = courseService.datagrid(course);
		if (vo.getTotal() > 0) {
			CourseVO courseVO = (CourseVO) vo.getRows().get(0);
			return courseVO;
		}
		return null;
	}

	private boolean hasAttendance(AttendanceVO vo) {
		List<AttendanceVO> retlist = attendanceService.queryAttendanceByStudentAndCourse(vo);
		if (retlist.size() > 0) {
			return true;
		}
		return false;
	}
	
}
